#include "pwm_sysfs.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 相对路径
#define DUTY_PATH "/duty_cycle"
#define PERIOD_PATH "/period"
#define ENABLE_PATH "/enable"
#define POLARITY_PATH "/polarity"
const char *pwm_polarity_str[2] = {
    "\"normal\"",
    "\"inversed\""
};

static char temp_path[64];
// 打开文件辅助函数
static int open_fp(pwm_t *pwm, const char *relative_path, FILE **fp)
{
    memset(temp_path, 0, sizeof(temp_path));
    snprintf(temp_path, sizeof(temp_path), "%s%s", pwm->path, relative_path);
    *fp = fopen(temp_path, "w");
    if (!*fp)
        return -1;
    return 0;
}

int pwm_open(pwm_t *pwm, int chip, int channel)
{
    pwm->chip = chip;
    pwm->channel = channel;

    // export
    FILE *export_fp = NULL;
    snprintf(temp_path, sizeof(temp_path),
             "/sys/class/pwm/pwmchip%d/export", chip);
    export_fp = fopen(temp_path, "w");
    if (!export_fp)
        return -1;
    fprintf(export_fp, "%d", channel);
    fclose(export_fp);

    // 构建路径
    snprintf(pwm->path, sizeof(pwm->path),
             "/sys/class/pwm/pwmchip%d/pwm%d", chip, channel);
    // 打开各个文件
    if (open_fp(pwm, PERIOD_PATH, &pwm->period_fp) < 0)
        return -1;
    if (open_fp(pwm, DUTY_PATH, &pwm->duty_cycle_fp) < 0)
        return -1;
    if (open_fp(pwm, ENABLE_PATH, &pwm->enable_fp) < 0)
        return -1;
    if (open_fp(pwm, POLARITY_PATH, &pwm->polarity_fp) < 0)
        return -1;
    return 0;
}

int pwm_close(pwm_t *pwm)
{
    if (pwm->period_fp)
        fclose(pwm->period_fp);
    if (pwm->duty_cycle_fp)
        fclose(pwm->duty_cycle_fp);
    if (pwm->enable_fp)
        fclose(pwm->enable_fp);
    if (pwm->polarity_fp)
        fclose(pwm->polarity_fp);

    // unexport
    FILE *unexport_fp = NULL;
    snprintf(temp_path, sizeof(temp_path),
             "/sys/class/pwm/pwmchip%d/unexport", pwm->chip);
    unexport_fp = fopen(temp_path, "w");
    if (!unexport_fp)
        return -1;
    fprintf(unexport_fp, "%d", pwm->channel);
    fclose(unexport_fp);
    return 0;
}

int pwm_set_period(pwm_t *pwm, unsigned int period_ns)
{
    if (!pwm->period_fp)
        return -1;
    fprintf(pwm->period_fp, "%u", period_ns);
    fflush(pwm->period_fp);
    return 0;
}

int pwm_set_duty_cycle(pwm_t *pwm, unsigned int duty_cycle_ns)
{
    if (!pwm->duty_cycle_fp)
        return -1;
    fprintf(pwm->duty_cycle_fp, "%u", duty_cycle_ns);
    fflush(pwm->duty_cycle_fp);
    return 0;
}

int pwm_enable(pwm_t *pwm, int enable)
{
    if (!pwm->enable_fp)
        return -1;
    fprintf(pwm->enable_fp, "%d", !!enable); // 强制 0/1
    fflush(pwm->enable_fp);
    return 0;
}

int pwnm_set_polarity(pwm_t *pwm, pwm_polarity_t polarity)
{
    if (!pwm->polarity_fp)
        return -1;
    fprintf(pwm->polarity_fp, "%s", pwm_polarity_str[polarity]);
    fflush(pwm->polarity_fp);
    return 0;
}

int pwm_operate(pwm_t *pwm, int period_ns, int duty_cycle_ns, pwm_polarity_t polarity)
{
    if (pwm->path[0] == '\0')
        return -1;

    pwm_enable(pwm, 0); // 先禁用
    pwm_set_period(pwm, period_ns);
    pwm_set_duty_cycle(pwm, duty_cycle_ns);
    pwnm_set_polarity(pwm, polarity);
    pwm_enable(pwm, 1); // 最后使能
    return 0;
}
